﻿using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;

namespace DB.SchemaSync.Library.Models
{
    /// <summary>
    /// 触发器
    /// </summary>
    public class Trigger : DbObject
    {
        [JsonIgnore]
        public Table Table { get; set; }

        public int Parent_Id { get; set; }

        /// <summary>
        /// 触发器名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 是否及
        /// </summary>
        public bool Is_Instead_Of { get; set; }

        /// <summary>
        /// 是否停用
        /// </summary>
        public bool Is_Disabled { get; set; }

        /// <summary>
        /// 类型
        /// </summary>
        public string type { get; set; }

        /// <summary>
        /// 事件
        /// </summary>
        public IEnumerable<Trigger_Event> Events { get; set; }

        /// <summary>
        /// 类型描述
        /// </summary>
        public string type_desc { get; set; }

        /// <summary>
        /// 创建触发器的sql
        /// </summary>
        public string CreateSql { get; set; } = "";

        public override IEnumerable<string> CreateCommands(SqlSyntax syntax)
        {
            //throw new NotImplementedException("触发器创建暂未实现");
            yield return CreateSql;
        }

        public override IEnumerable<string> DropCommands(SqlSyntax syntax)
        {
            //throw new NotImplementedException("触发器创建暂未实现");
            yield return $"DROP TRIGGER <{Name}>";

        }

        public override IEnumerable<string> AlterCommands(SqlSyntax syntax, Database database)
        {
            if (!string.IsNullOrEmpty(AlterDescription)) yield return $"{syntax.CommentStart} {AlterDescription}";
            foreach (var cmd in base.AlterCommands(syntax, database)) yield return cmd;
        }


        //是否变化
        public override bool IsAltered(DbObject compare)
        {
            var test = compare as Trigger;
            if (test != null)
            {
                if (Is_Instead_Of != test.Is_Instead_Of)
                {
                    AlterDescription = $"tirgger {Name} Is_Instead_Of changed from {Is_Instead_Of} to {test.Is_Instead_Of}";

                    return true;
                }

                if (!test.Events.SequenceEqual(Events))
                {
                    string newColumns = string.Join(", ", Events.Select(col => $"{col.type_desc}"));
                    string oldColumns = string.Join(", ", test.Events.Select(col => $"{col.type_desc}"));
                    AlterDescription = $"tirgger {Name} events changed from {oldColumns} to {newColumns}";
                    return true;
                }
            }
            return false;
        }

        public override IEnumerable<DbObject> GetDependencies(Database database)
        {
            return base.GetDependencies(database);
        }

        public override bool Equals(object obj)
        {
            var test = obj as Trigger;
            if (test != null)
            {
                return test.Table.Equals(Table) && test.Name.ToLower().Equals(Name.ToLower());
            }

            return false;
        }

        public override string ToString()
        {
            return $"{Table}.{Name}";
        }

        public override int GetHashCode()
        {
            return Table.GetHashCode() + Name.ToLower().GetHashCode();
        }

        public override ExcludeObject GetExcludeObject()
        {
            return new ExcludeObject() { Type = "Trigger", Name = Table.ToString() + "." + Name };
        }

    }

    /// <summary>
    /// 事件类型
    /// </summary>
    public enum TriggerType
    {
        INSERT = 1,
        UPDATE = 2,
        DELETE = 3
    }

    /// <summary>
    /// 触发器事件
    /// </summary>
    public class Trigger_Event
    {
        public int ObjectId { get; set; }
        public TriggerType type { get; set; }
        public string type_desc { get; set; }
        public bool is_trigger_event { get; set; }

        public override bool Equals(object obj)
        {
            Trigger_Event test = obj as Trigger_Event;
            if (test != null)
            {
                return test.ObjectId == ObjectId && test.type == type && test.is_trigger_event == is_trigger_event ;
            }
            return false;
        }
    }
}
